package com.lqian.juc;

import java.util.concurrent.Semaphore;

/**
 * 再修改一下，演示个非典型的 Semaphore 用法。
 * 注意，上面的代码，更侧重的是演示 Semaphore 的功能以及局限性，
 * 其实有很多线程编程中的反实践，比如使用了 sleep 来协调任务执行，
 * 而且使用轮询调用 availalePermits 来检测信号量获取情况，
 * 这都是很低效并且脆弱的，通常只是用在测试或者诊断场景。
 *
 * 总的来说 Semaphore就是一个计数器，其基本逻辑基于acquire/release，并没有太复杂的同步逻辑
 *
 * 如过Semaphore的数值被初始化为1，那么一个线程就可以通过acquire进入互斥状态，本质上和互斥锁是非常相似的。
 * 但是区别也是非常明显，比如互斥锁是有持有者的，而对于Semaphore这种计算器结构，虽然有类似功能，但是其实并不存在持有者
 * 除非我们进行扩展包装。
 * @author：Melody_LQ
 * @time：2022/8/29 9:47 上午
 */
public class SemaphoreDemo02 {
    public static void main(String[] args) throws InterruptedException {
        Semaphore semaphore = new Semaphore(0);
        for (int i = 0; i <10 ; i++) {
            Thread thread = new Thread(new MyWorker(semaphore));
            thread.start();
        }
        System.out.println("Action...GO!");
        semaphore.release(5);
        System.out.println("Waiting for permits off");
        while(semaphore.availablePermits() != 0){
            Thread.sleep(100L);
        }
        System.out.println("Action...GO again!");
        semaphore.release(5);
    }


}
class MyWorker implements  Runnable{
    private Semaphore semaphore;

    public MyWorker(Semaphore semaphore) {
        this.semaphore = semaphore;
    }

    @Override
    public void run() {
        try {
            semaphore.acquire();
            System.out.println("Executed!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}